package com.xxchat.aspect;

import com.xxchat.annotation.GlobalInterceptor;
import com.xxchat.entity.dto.TokenUserInfoDTO;
import com.xxchat.entity.enums.ResponseCodeEnum;
import com.xxchat.exception.BusinessException;
import com.xxchat.redis.RedisComponent;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author Waicc
 */
@Aspect
@Component("globalOperationAspect")
public class GlobalOperationAspect {
    @Resource
    private RedisComponent redisComponent;

    private static final Logger log = LoggerFactory.getLogger(GlobalOperationAspect.class);

    @Before("@annotation(com.xxchat.annotation.GlobalInterceptor)")
    public void interceptorDo(JoinPoint joinPoint) {
        try {
            Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
            GlobalInterceptor globalInterceptor = method.getAnnotation(GlobalInterceptor.class);
            if (globalInterceptor == null) {
                return;
            }
            if (globalInterceptor.checkLogin() || globalInterceptor.checkAdmin()) {
                checkLogin(globalInterceptor.checkAdmin());
            }
        } catch (BusinessException e) {
            log.error("全局拦截异常", e);
            throw e;
        } catch (Exception e) {
            log.error("全局拦截异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        } catch (Throwable e) {
            log.error("全局拦截异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        }
    }

    private void checkLogin(boolean checkAdmin) {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            throw new BusinessException(ResponseCodeEnum.CODE_401);
        }
        TokenUserInfoDTO userInfo = redisComponent.getUserInfoByToken(token);
        if (userInfo == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_401);
        }
        if (checkAdmin && !userInfo.getAdmin()) {
            throw new BusinessException(ResponseCodeEnum.CODE_401);
        }
    }
}